package logic

import (
	"MoSkeleton/framework/core/dto/request"
	"MoSkeleton/framework/core/dto/response"
	"MoSkeleton/framework/core/models"
	"MoSkeleton/framework/utils"
	"MoSkeleton/models/tool"
	mapset "github.com/deckarep/golang-set/v2"
	"github.com/samber/lo"
	"html/template"
	"reflect"
	"strings"
	"unicode"
)

//html/template 模板的自定义函数

var MoTplFuncMap template.FuncMap

var ignoreModelColumnSet mapset.Set[string]
var ignorePageReqColumnSet mapset.Set[string]
var ignoreUpdateReqColumnSet mapset.Set[string]
var ignoreItemRespColumnSet mapset.Set[string]

// model : 生成column 信息的过滤器
// 返回： false 不生成
func GenModelColumnNameFilter(columnName string) bool {
	// 判断columnName 是否在ignoreColumnMap中
	return !ignoreModelColumnSet.ContainsOne(strings.ToLower(columnName))
}

// req: 生成request column信息过滤器
// 返回： false 不生成
func GenPageReqColumnNameFilter(columnName string) bool {
	return !ignorePageReqColumnSet.ContainsOne(strings.ToLower(columnName))
}

func GenUpdateReqColumnNameFilter(columnName string) bool {
	return !ignoreUpdateReqColumnSet.ContainsOne(strings.ToLower(columnName))
}
func GenItemRespColumnNameFilter(columnName string) bool {
	return !ignoreItemRespColumnSet.ContainsOne(strings.ToLower(columnName))
}

func JsonStringTagForColumn(goType string) string {
	if "uint64" == goType || "int64" == goType {
		return ",string"
	}
	return ""
}

func FirstLetterLower(str string) string {
	if len(str) == 0 {
		return str
	}
	runes := []rune(str)
	runes[0] = unicode.ToLower(runes[0])
	return string(runes)
}
func FirstLetterUp(str string) string {
	if len(str) == 0 {
		return str
	}
	runes := []rune(str)
	runes[0] = unicode.ToUpper(runes[0])
	return string(runes)
}
func ContainField(columns []*tool.GenTableColumn, searchFieldName string) bool {
	for _, column := range columns {
		if strings.ToLower(column.ColumnName) == strings.ToLower(searchFieldName) {
			return true
		}
	}
	return false
}

// vue 前端代码生成器模板自定义函数
func IsVueQueryParam(columnName string, isQuery string) bool {
	if isQuery == "0" {
		return false
	}
	ignoreQueryParams := []string{"id", "created_by", "updated_by", "updated_at"}
	if lo.Contains(ignoreQueryParams, strings.ToLower(columnName)) {
		return false
	}
	return true
}

func IsVueList(columnName string, isList string) bool {
	if !IsVueFormParam(columnName) {
		return false
	}
	return !(isList == "0")
}

func IsVueFormParam(columnName string) bool {
	ignoreFormParams := []string{"created_by", "updated_by", "updated_at", "created_at"}
	if lo.Contains(ignoreFormParams, strings.ToLower(columnName)) {
		return false
	}
	return true
}

func IsVueFormEdit(columnName, isEdit string) bool {
	if isEdit == "0" {
		return false
	}
	ignoreFormParams := []string{"id", "created_by", "updated_by", "updated_at", "created_at"}
	if lo.Contains(ignoreFormParams, strings.ToLower(columnName)) {
		return false
	}
	return true
}
func IsVueDatetimeType(columnType string) bool {
	datetimeTypes := []string{"datetime", "date", "time"}
	return lo.Contains(datetimeTypes, strings.ToLower(columnType))
}

func IsVueStrType(columnType string) bool {
	strTypes := []string{"varchar", "char", "text", "longtext"}
	return lo.Contains(strTypes, columnType)
}

func IsVueNumberType(columnType string) bool {
	numberTypes := []string{"int", "float", "double", "decimal", "tinyint", "smallint", "mediumint", "bigint", "unsigned big int", "unsigned small int", "unsigned medium int", "unsigned int", "unsigned tiny int"}
	return lo.Contains(numberTypes, columnType)
}

func GetVueTypeDefaultVal(columnType string) any {
	//if IsVueStrType(columnType) {
	//	return ""
	//} else if IsVueNumberTypeWithoutFloat(columnType) {
	//	return 0
	//} else if IsVueNumberType(columnType) {
	//	return 0.0
	//} else if IsVueDatetimeType(columnType) {
	//	return 0
	//} else {
	//	return ""
	//}
	return "undefined"
}

func IsVueRequiredColumn(isRequired string) bool {
	return isRequired == "1"
}

// 不带浮点的数字类型
func IsVueNumberTypeWithoutFloat(columnType string) bool {
	numberTypes := []string{"int", "tinyint", "smallint", "mediumint", "bigint", "unsigned big int", "unsigned small int", "unsigned medium int", "unsigned int", "unsigned tiny int"}
	return lo.Contains(numberTypes, columnType)
}

// 定义自定义管道函数
func safeJS(s string) template.JS {
	return template.JS(s)
}
func initIgnoreModelColumns() {
	var moModel = models.MoModel{}
	ignoreModelColumnSet = mapset.NewSet[string]()
	initSetByColumns(ignoreModelColumnSet, moModel)
}

func initIgnorePageReqColumns() {
	var pageInfo = request.PageInfo{}
	var baseReq = request.BaseRequest{}
	var idOptional = request.IDRequestOptional{}
	ignorePageReqColumnSet = mapset.NewSet[string]()
	initSetByColumns(ignorePageReqColumnSet, pageInfo)
	initSetByColumns(ignorePageReqColumnSet, baseReq)
	initSetByColumns(ignorePageReqColumnSet, idOptional)
}

func initIgnoreUpdateReqColumns() {
	var idReq = request.IDRequest{}
	ignoreUpdateReqColumnSet = mapset.NewSet[string]()
	initSetByColumns(ignoreUpdateReqColumnSet, idReq)
}

func initIgnoreItemRespColumns() {
	var itemResp = response.ModelResp{}
	ignoreItemRespColumnSet = mapset.NewSet[string]()
	initSetByColumns(ignoreItemRespColumnSet, itemResp)
}

func initSetByColumns(columnSet mapset.Set[string], item any) {
	var itemType = reflect.TypeOf(item)
	for i := 0; i < itemType.NumField(); i++ {
		field := itemType.Field(i)
		columnSet.Add(strings.ToLower(field.Name))
	}
}

func init() {
	initIgnoreModelColumns()
	initIgnorePageReqColumns()
	initIgnoreUpdateReqColumns()
	initIgnoreItemRespColumns()
	MoTplFuncMap = template.FuncMap{
		"GenModelColumnNameFilter":     GenModelColumnNameFilter,
		"GenPageReqColumnNameFilter":   GenPageReqColumnNameFilter,
		"GenUpdateReqColumnNameFilter": GenUpdateReqColumnNameFilter,
		"JsonStringTagForColumn":       JsonStringTagForColumn,
		"GenItemRespColumnNameFilter":  GenItemRespColumnNameFilter,
		"FirstLetterLower":             FirstLetterLower,
		"FirstLetterUp":                FirstLetterUp,
		"ContainField":                 ContainField,
		"ReplaceStrInsensitive":        utils.ReplaceStrInsensitive,
		"ReplaceStrAllInsensitive":     utils.ReplaceStrAllInsensitive,
		//vue
		"IsVueQueryParam":      IsVueQueryParam,
		"IsVueDatetimeType":    IsVueDatetimeType,
		"IsVueStrType":         IsVueStrType,
		"IsVueNumberType":      IsVueNumberType,
		"GetVueTypeDefaultVal": GetVueTypeDefaultVal,
		"IsVueFormParam":       IsVueFormParam,
		"IsVueRequiredColumn":  IsVueRequiredColumn,
		"IsVueFormEdit":        IsVueFormEdit,
		"IsVueList":            IsVueList,
		//
		"safeJS": safeJS,
	}
}
